package test.org.dbstar.scheduler.control;

import java.util.List;

import org.dbstar.scheduler.beans.Catalog;
import org.dbstar.scheduler.control.CatalogController;
import org.dbstar.scheduler.control.exception.DaoException;

import test.org.dbstar.scheduler.JdbcTemplateTestCase;


/**
 * 测试CatalogController的TestCase基类
 * 
 * @author 代波
 * @since 1.0.0
 * @version 1.0.0
 * @date 2012-4-21
 */
public abstract class CatalogControllerTestCase extends JdbcTemplateTestCase {
	private CatalogController controller;
	private Catalog root;
	private int rootId;

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		controller = buildCatalogController();
		root = controller.getRootCatalog();
		rootId = root.getId();
	}

	@Override
	protected void tearDown() throws Exception {
		controller = null;
		super.tearDown();
	}

	protected abstract CatalogController buildCatalogController() throws DaoException;

	private void checkEqualsRoot(Catalog info) throws DaoException {
		checkEquals(info, root);
	}

	private void checkEquals(Catalog c1, Catalog c2) {
		assertEquals(c1.getId(), c2.getId());
		assertEquals(c1.getName(), c2.getName());
		assertEquals(c1.getParent(), c2.getParent());
		assertEquals(c1.getDescription(), c2.getDescription());
		assertEquals(c1.getCreateTime(), c2.getCreateTime());
		assertEquals(c1.getModifyTime(), c2.getModifyTime());
		assertEquals(c1, c2);
	}

	private Catalog newCataLog(int parent, String name, String desc) {
		Catalog catalog = new Catalog();
		catalog.setParent(parent);
		catalog.setName(name);
		catalog.setDescription(desc);
		catalog.setOwner("dbai");
		return catalog;
	}

	private Catalog newCataLog(int parent, String name, String desc, long createTime) {
		Catalog catalog = newCataLog(parent, name, desc);
		catalog.setCreateTime(createTime);
		return catalog;
	}

	public void testGetRootCatalog() throws DaoException {
		Catalog root = controller.getRootCatalog();
		assertNotNull(root);
		assertTrue(root.getId() > 0);
		assertEquals("root", root.getName());
		assertNull(root.getParent());
		assertEquals("根目录", root.getDescription());
		assertTrue(root.getCreateTime() > 0 && root.getCreateTime() <= System.currentTimeMillis());
		assertNull(root.getModifyTime());
	}

	public void testGetAllCatalogs() throws DaoException {
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(1, list.size());
		checkEqualsRoot(list.get(0));
	}

	public void testGetSubCatalogs() throws DaoException {
		assertEquals(0, controller.getSubCatalogs(0).size());
		assertEquals(0, controller.getSubCatalogs(1).size());
	}

	public void testGetCatalog() throws DaoException {
		assertNull(controller.getCatalog(0));
		checkEqualsRoot(controller.getCatalog(rootId));
	}

	// 测试增加parent为已存在分类
	public void testAddCatalog() throws DaoException {
		long ct = System.currentTimeMillis();
		Catalog newInfo = newCataLog(rootId, "name", "desc", ct);
		newInfo.setId(100);
		newInfo.setModifyTime(System.currentTimeMillis());

		// 传入对象的ID值会被正确设置为自动生成的ID，且通过addCatalog方法返回
		assertEquals(controller.addCatalog(newInfo), newInfo.getId());

		assertTrue(newInfo.getId() > 0);// id会是个大于0的值
		assertNotSame(10000, newInfo.getId());// 传入对象的ID值会被覆盖
		assertEquals(newInfo.getName(), "name");
		assertEquals(newInfo.getParent().intValue(), rootId);
		assertEquals(newInfo.getDescription(), "desc");
		assertEquals(newInfo.getCreateTime(), ct);
		assertNull(newInfo.getModifyTime());// 传入对象的最后生成时间会被设置为null

		checkEquals(newInfo, controller.getCatalog(newInfo.getId()));

		List<Catalog> list = controller.getAllCatalogs();
		// 现在有两个分类了
		assertEquals(2, list.size());
		// 按照parent,id排序，第一个分类是root，第二个分类是newCatalog
		checkEqualsRoot(list.get(0));
		checkEquals(newInfo, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(newInfo, list.get(0));
	}

	// 其他允许Null的值
	public void testAddCatalogNullable() throws DaoException {
		Catalog newInfo = newCataLog(rootId, "name", null);

		// 传入对象的ID值会被正确设置为自动生成的ID，且通过addCatalog方法返回
		assertEquals(controller.addCatalog(newInfo), newInfo.getId());

		assertTrue(newInfo.getId() > 0);// id会是个大于0的值
		assertEquals(newInfo.getName(), "name");
		assertEquals(newInfo.getParent().intValue(), rootId);
		assertNull(newInfo.getDescription());
		assertTrue(newInfo.getCreateTime() > 0 && newInfo.getCreateTime() <= System.currentTimeMillis());
		assertNull(newInfo.getModifyTime());// 传入对象的最后生成时间会被设置为null

		checkEquals(newInfo, controller.getCatalog(newInfo.getId()));

		List<Catalog> list = controller.getAllCatalogs();
		// 现在有两个分类了
		assertEquals(2, list.size());
		// 按照parent,id排序，第一个分类是root，第二个分类是newCatalog
		checkEqualsRoot(list.get(0));
		checkEquals(newInfo, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(newInfo, list.get(0));
	}

	// 测试增加parent为不存在分类
	public void testAddCatalogParentNotExist() throws DaoException {
		Catalog newInfo = newCataLog(10000, "name", "desc");
		newInfo.setId(100);
		long mt = System.currentTimeMillis();
		newInfo.setModifyTime(mt);

		try {
			controller.addCatalog(newInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
		assertEquals(newInfo.getId(), 100);
		assertEquals(newInfo.getModifyTime().longValue(), mt);

		assertNull(controller.getCatalog(100));

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(1, list.size());
		checkEqualsRoot(list.get(0));

		assertEquals(0, controller.getSubCatalogs(10000).size());
	}

	// name不能为null
	public void testAddCatalogNameNull() throws DaoException {
		Catalog newInfo = newCataLog(rootId, null, "desc");
		newInfo.setId(100);
		long mt = System.currentTimeMillis();
		newInfo.setModifyTime(mt);

		try {
			controller.addCatalog(newInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
		assertEquals(newInfo.getId(), 100);
		assertEquals(newInfo.getModifyTime().longValue(), mt);

		assertNull(controller.getCatalog(100));

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(1, list.size());
		checkEqualsRoot(list.get(0));

		assertEquals(0, controller.getSubCatalogs(rootId).size());
	}

	// name不能仅仅为空格字符组成
	public void testAddCatalogNameBlank() throws DaoException {
		Catalog newInfo = newCataLog(rootId, " \t ", "desc");
		newInfo.setId(100);
		long mt = System.currentTimeMillis();
		newInfo.setModifyTime(mt);

		try {
			controller.addCatalog(newInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
		assertEquals(newInfo.getId(), 100);
		assertEquals(newInfo.getModifyTime().longValue(), mt);

		assertNull(controller.getCatalog(100));

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(1, list.size());
		checkEqualsRoot(list.get(0));

		assertEquals(0, controller.getSubCatalogs(rootId).size());
	}

	// 相同parent下的所有Catalog的name不能重名
	public void testAddCatalogNameRepeat() throws DaoException {
		controller.addCatalog(newCataLog(rootId, "name", "desc"));

		try {
			controller.addCatalog(newCataLog(rootId, "name", "desc2"));
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(2, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
	}

	public void testUpdateCatalog() throws DaoException {
		Integer c1 = controller.addCatalog(newCataLog(rootId, "name1", "desc1"));
		long ct = System.currentTimeMillis();
		int c2 = controller.addCatalog(newCataLog(rootId, "name2", "desc2", ct));

		Catalog editInfo = controller.getCatalog(c2);
		editInfo.setParent(c1);
		editInfo.setName("name3");
		editInfo.setDescription("desc3");
		editInfo.setCreateTime(System.currentTimeMillis());
		controller.updateCatalog(editInfo);

		Catalog info = controller.getCatalog(c2);
		assertEquals(info.getName(), "name3");
		assertEquals(info.getParent(), c1);
		assertEquals(info.getDescription(), "desc3");
		assertEquals(info.getCreateTime(), ct);// 创建时间不变
		assertTrue(info.getModifyTime() != null && info.getModifyTime().longValue() > 0
				&& info.getModifyTime().longValue() <= System.currentTimeMillis());// 修改时间自动设置

		editInfo.setCreateTime(ct);
		checkEquals(editInfo, info);

		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(3, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(controller.getCatalog(c1), list.get(1));
		checkEquals(info, list.get(2));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(controller.getCatalog(c1), list.get(0));

		list = controller.getSubCatalogs(c1);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));
	}

	public void testUpdateCatalogNullable() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		Catalog editInfo = controller.getCatalog(c1);
		editInfo.setName("name3");
		editInfo.setDescription(null);
		controller.updateCatalog(editInfo);

		Catalog info = controller.getCatalog(c1);
		assertEquals(info.getName(), "name3");
		assertEquals(info.getParent().longValue(), rootId);
		assertNull(info.getDescription());
		assertTrue(info.getCreateTime() > 0 && info.getCreateTime() <= System.currentTimeMillis());// 创建时间自动设置
		assertTrue(info.getModifyTime() != null && info.getModifyTime().longValue() > 0
				&& info.getModifyTime().longValue() <= System.currentTimeMillis());// 修改时间自动设置

		checkEquals(editInfo, info);

		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(2, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(info, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));
	}

	public void testUpdateCatalogParentNotExist() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		Catalog editInfo = controller.getCatalog(c1);
		editInfo.setParent(10000);
		editInfo.setName("name3");
		editInfo.setDescription("desc3");
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
		assertNull(editInfo.getModifyTime());// 传入对象未被更新

		Catalog info = controller.getCatalog(c1);
		// 未变化
		assertEquals(info.getId(), c1);
		assertEquals(info.getName(), "name");
		assertEquals(info.getParent().intValue(), rootId);
		assertEquals(info.getDescription(), "desc");
		assertNull(info.getModifyTime());

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(2, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(info, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));

		assertEquals(0, controller.getSubCatalogs(10000).size());
	}

	public void testUpdateCatalogNameNull() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		Catalog editInfo = controller.getCatalog(c1);
		editInfo.setName(null);
		editInfo.setDescription("desc3");
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
		assertNull(editInfo.getModifyTime());// 传入对象未被更新

		Catalog info = controller.getCatalog(c1);
		// 未变化
		assertEquals(info.getId(), c1);
		assertEquals(info.getName(), "name");
		assertEquals(info.getParent().intValue(), rootId);
		assertEquals(info.getDescription(), "desc");
		assertNull(info.getModifyTime());

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(2, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(info, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));
	}

	public void testUpdateCatalogNameBlank() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		Catalog editInfo = controller.getCatalog(c1);
		editInfo.setName(" \t ");
		editInfo.setDescription("desc3");
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
		assertNull(editInfo.getModifyTime());// 传入对象未被更新

		Catalog info = controller.getCatalog(c1);
		// 未变化
		assertEquals(info.getId(), c1);
		assertEquals(info.getName(), "name");
		assertEquals(info.getParent().intValue(), rootId);
		assertEquals(info.getDescription(), "desc");
		assertNull(info.getModifyTime());

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(2, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(info, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));
	}

	public void testUpdateCatalogNameRepeat() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name1", "desc1"));
		int c2 = controller.addCatalog(newCataLog(c1, "name2", "desc2"));
		int c3 = controller.addCatalog(newCataLog(c1, "name3", "desc3"));

		// 与c2重名且同parent
		Catalog editInfo = controller.getCatalog(c3);
		editInfo.setName("name2");
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(2, controller.getSubCatalogs(c1).size());

		// 与c1重名且同parent
		editInfo = controller.getCatalog(c3);
		editInfo.setParent(rootId);
		editInfo.setName("name1");
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(2, controller.getSubCatalogs(c1).size());

		// 与c1重名但不同parent
		editInfo = controller.getCatalog(c3);
		editInfo.setParent(c2);
		editInfo.setName("name1");
		controller.updateCatalog(editInfo);

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());
		assertEquals(1, controller.getSubCatalogs(c2).size());
	}

	public void testUpdateCatalogParentSame() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		Catalog editInfo = controller.getCatalog(c1);
		editInfo.setParent(c1);
		editInfo.setName("name3");
		editInfo.setDescription("desc3");
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
		assertNull(editInfo.getModifyTime());// 传入对象未被更新

		Catalog info = controller.getCatalog(c1);
		// 未变化
		assertEquals(info.getId(), c1);
		assertEquals(info.getName(), "name");
		assertEquals(info.getParent().intValue(), rootId);
		assertEquals(info.getDescription(), "desc");
		assertNull(info.getModifyTime());

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(2, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(info, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));

		assertEquals(0, controller.getSubCatalogs(c1).size());
	}

	public void testUpdateCatalogParentLoop() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name1", "desc1"));
		int c2 = controller.addCatalog(newCataLog(c1, "name2", "desc2"));
		int c3 = controller.addCatalog(newCataLog(c2, "name3", "desc3"));

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());
		assertEquals(1, controller.getSubCatalogs(c2).size());

		// 间接子嵌套
		Catalog editInfo = controller.getCatalog(c1);
		editInfo.setParent(c3);
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());
		assertEquals(1, controller.getSubCatalogs(c2).size());

		// 直接子嵌套
		editInfo = controller.getCatalog(c2);
		editInfo.setParent(c3);
		try {
			controller.updateCatalog(editInfo);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());
		assertEquals(1, controller.getSubCatalogs(c2).size());
	}

	public void testUpdateCatalogRoot() throws DaoException {
		Catalog cataLog = controller.getRootCatalog();
		cataLog.setName("name");
		try {
			controller.updateCatalog(cataLog);
			fail("应该抛出DaoException，root不能更新。");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(1, list.size());
		checkEqualsRoot(list.get(0));
	}

	public void testUpdateCatalogNotExist() throws DaoException {
		Catalog cataLog = newCataLog(rootId, "name", "desc");
		cataLog.setId(100);
		try {
			controller.updateCatalog(cataLog);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}

	public void testMoveCatalog() throws DaoException {
		Integer c1 = controller.addCatalog(newCataLog(rootId, "name1", "desc1"));
		long ct = System.currentTimeMillis();
		int c2 = controller.addCatalog(newCataLog(rootId, "name2", "desc2", ct));

		controller.moveCatalog(c2, c1);

		Catalog info = controller.getCatalog(c2);
		assertEquals(info.getName(), "name2");
		assertEquals(info.getParent(), c1);
		assertEquals(info.getDescription(), "desc2");
		assertEquals(info.getCreateTime(), ct);// 创建时间不变
		assertNull(info.getModifyTime());// 不更新最后修改时间

		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(3, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(controller.getCatalog(c1), list.get(1));
		checkEquals(info, list.get(2));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(controller.getCatalog(c1), list.get(0));

		list = controller.getSubCatalogs(c1);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));
	}

	public void testMoveCatalogParentNotExist() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		try {
			controller.moveCatalog(c1, 10000);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		Catalog info = controller.getCatalog(c1);
		// 未变化
		assertEquals(info.getId(), c1);
		assertEquals(info.getName(), "name");
		assertEquals(info.getParent().intValue(), rootId);
		assertEquals(info.getDescription(), "desc");
		assertNull(info.getModifyTime());

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(2, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(info, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));

		assertEquals(0, controller.getSubCatalogs(10000).size());
	}

	public void testMoveCatalogNameRepeat() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name1", "desc1"));
		controller.addCatalog(newCataLog(c1, "name2", "desc2"));
		int c3 = controller.addCatalog(newCataLog(c1, "name1", "desc1"));

		// 与c1重名且同parent
		try {
			controller.moveCatalog(c3, rootId);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(2, controller.getSubCatalogs(c1).size());

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(2, controller.getSubCatalogs(c1).size());
	}

	public void testMoveCatalogParentSame() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		try {
			controller.moveCatalog(c1, c1);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		Catalog info = controller.getCatalog(c1);
		// 未变化
		assertEquals(info.getId(), c1);
		assertEquals(info.getName(), "name");
		assertEquals(info.getParent().intValue(), rootId);
		assertEquals(info.getDescription(), "desc");
		assertNull(info.getModifyTime());

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(2, list.size());
		checkEqualsRoot(list.get(0));
		checkEquals(info, list.get(1));

		list = controller.getSubCatalogs(rootId);
		assertEquals(1, list.size());
		checkEquals(info, list.get(0));

		assertEquals(0, controller.getSubCatalogs(c1).size());
	}

	public void testMoveCatalogParentLoop() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name1", "desc1"));
		int c2 = controller.addCatalog(newCataLog(c1, "name2", "desc2"));
		int c3 = controller.addCatalog(newCataLog(c2, "name3", "desc3"));

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());
		assertEquals(1, controller.getSubCatalogs(c2).size());

		// 间接子嵌套
		try {
			controller.moveCatalog(c1, c3);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());
		assertEquals(1, controller.getSubCatalogs(c2).size());

		// 直接子嵌套
		try {
			controller.moveCatalog(c2, c3);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(4, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());
		assertEquals(1, controller.getSubCatalogs(c2).size());
	}

	public void testMoveCatalogNotExist() throws DaoException {
		try {
			controller.moveCatalog(100, rootId);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}

	public void testRemoveCatalog() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name", "desc"));

		assertEquals(2, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());

		controller.removeCatalog(c1);
		assertEquals(1, controller.getAllCatalogs().size());
		assertEquals(0, controller.getSubCatalogs(1).size());
	}

	public void testRemoveCatalogNotExist() throws DaoException {
		try {
			controller.removeCatalog(100);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}

	public void testRemoveCatalogHasSub() throws DaoException {
		int c1 = controller.addCatalog(newCataLog(rootId, "name1", "desc1"));
		int c2 = controller.addCatalog(newCataLog(c1, "name2", "desc2"));

		assertEquals(3, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());

		try {
			controller.removeCatalog(c1);
			fail("应该抛出DaoException");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		assertEquals(3, controller.getAllCatalogs().size());
		assertEquals(1, controller.getSubCatalogs(rootId).size());
		assertEquals(1, controller.getSubCatalogs(c1).size());

		controller.removeCatalog(c2);
		controller.removeCatalog(c1);

		assertEquals(1, controller.getAllCatalogs().size());
		assertEquals(0, controller.getSubCatalogs(rootId).size());
		assertEquals(0, controller.getSubCatalogs(c1).size());
	}

	public void testRemoveCatalogRoot() throws DaoException {
		try {
			controller.removeCatalog(rootId);
			fail("应该抛出DaoException，root不能被删除。");
		} catch (DaoException e) {
			e.printStackTrace();
		}

		// 现有分类不变
		List<Catalog> list = controller.getAllCatalogs();
		assertEquals(1, list.size());
		checkEqualsRoot(list.get(0));
	}
}
